#ifndef LINCOMM_HPP
#define LINCOMM_HPP

#include "comm_interface.hpp"
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <atomic>
#include <vector>
#include <list>
#include "spdlog/spdlog.h"
#include <libserialport.h>

/*LIN frame structure*/
//DATA[0]:  // Protected ID or CMD
// DATA[1]: // Data byte 0
// ......
// DATA[8]: // Data byte 6

class LinComm : public CommInterface {
public:
    explicit LinComm(const std::string& port, unsigned int baudrate);
    ~LinComm();

    bool initialize() override;
    bool send(const std::vector<uint8_t>& data) override;
    std::vector<uint8_t> receive() override;
    void registerCallback(DataReceivedCallback callback) override;
    std::string getName() const override;
    bool isConnected() const override;
    void shutdown() override;
//    void testSend() override;


    
private:
    void readThreadFunc();
    void processReceivedData();
    void send_sync_byte(sp_port *port);
    void send_lin_break(sp_port *port);
    uint8_t calculate_pid(uint8_t frame_id);
    uint8_t lin_checksum_enhanced(const uint8_t *data, uint8_t len, uint8_t pid);
    uint8_t lin_checksum_classic(const uint8_t *data, uint8_t len);

    std::string port_;
    unsigned int baudrate_;
    int fd_ = -1;
    std::atomic<bool> running_{false};
    
    std::thread readThread_;
    std::thread processThread_;
    std::mutex dataMutex_;
    std::condition_variable dataCond_;
    
    std::queue<std::vector<uint8_t>> receiveQueue_;
    
    DataReceivedCallback callback_;
    sp_port *port; 
    
    static constexpr size_t BUFFER_SIZE = 4096;
    uint8_t ringBuffer_[BUFFER_SIZE];
    size_t head_ = 0;
    size_t tail_ = 0;
};

#endif // LINCOMM_HPP